package cn.edu.sdjzu.xg.bysj.dao;

import cn.edu.sdjzu.xg.bysj.domain.Actor;
import cn.edu.sdjzu.xg.bysj.domain.JWT;
import cn.edu.sdjzu.xg.bysj.domain.Teacher;
import cn.edu.sdjzu.xg.bysj.domain.User;
import cn.edu.sdjzu.xg.bysj.service.ActorService;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import util.JdbcHelper;
import util.TokenHelper;

import java.sql.*;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;


public final class UserDao {
    private static final UserDao userDao = new UserDao();
    private static Collection<User> users;

    private UserDao() {
    }

    public static UserDao getInstance() {
        return userDao;
    }

    public static void main(String[] args)throws SQLException {
        UserDao dao = new UserDao();
        Collection<User> users = dao.findAll();
        display(users);
    }

    private static void display(Collection<User> users) {
        for (User user : users) {
            System.out.println(user);
        }
    }

    public Collection<User> findAll() throws SQLException {
        return UserDao.users;
    }

    public User find(Integer id)throws SQLException {
        User desiredUser = null;
        for (User user : users) {
            if (id.equals(user.getId())) {
                desiredUser = user;
                break;
            }
        }
        return desiredUser;
    }

    public boolean update(User user) throws SQLException {
        users.remove(user);
        return users.add(user);
    }

    public boolean add(User user)throws SQLException {
        return users.add(user);
    }

    /**
     * TeacherService.add在调用本方法之前，还会调用TeacherDao.add方法
     * 两次对Dao的调用要保证是同一Connection对象，才能将它们设置在同一事务中
     * @param user 要增加到数据库表中的User对象
     * @param connection 来自Service的Connection对象
     * @return 成功增加true，失败：false
     * @throws SQLException
     */
    public boolean add(User user, Connection connection) throws SQLException {
        //创建语句对象, 字段lastLoginTime 为“时间戳”类型，无须手动写入
        PreparedStatement pstmt =
                connection.prepareStatement("INSERT INTO user " +
                        " (username,password,actor_id)" +
                        " VALUES(?,?,?)");
        pstmt.setString(1, user.getUsername());
        pstmt.setString(2, user.getPassword());
        pstmt.setInt(3, user.getActor().getId());

        //执行语句
        int rowAffected = pstmt.executeUpdate();
        //事务未结束，不能释放资源
        return rowAffected > 0;
    }
    /**
     * 根据用户名查找
     * @param username 要查找的用户名
     * @return 符合条件的对象
     * @throws SQLException
     */
    public User findByName(String username) throws SQLException {
        User desiredUser = null;
        Connection connection = JdbcHelper.getConn();
        PreparedStatement preparedStatement =
                connection.prepareStatement("SELECT * FROM user WHERE username=?");
        preparedStatement.setString(1,username);
        ResultSet resultSet = preparedStatement.executeQuery();
        if(resultSet.next()){
            int id = resultSet.getInt("id");
            String password = resultSet.getString("password");
            Timestamp timestamp = resultSet.getTimestamp("lastLoginTime");
            LocalDateTime lastLoginTime = null;
            if(timestamp!=null) {
                lastLoginTime = timestamp.toLocalDateTime();
            }
            int teacherId = resultSet.getInt("teacher_id");
            Teacher teacherOfUser = TeacherDao.getInstance().find(teacherId, connection);
            //以当前元组的各个字段值为参数，创建User对象
            desiredUser =
                    new User(id,username,password,lastLoginTime,teacherOfUser);
        }
        return desiredUser;
    }
    /**
     *  用户名的基础部分在user表中存的情况下，调用本方法
    * @param username 用户名的基础部分，如:lkq
    * @return 用户名的基础部分+序号（整体用户名不存在），如:lkq5
    * @throws SQLException
    */
    public String generateUsername(String username)throws SQLException {
        //序列号初值为1
        int usernameSN = 1;
        //将参数和序列号连接起来，到表中查询
        while(this.findByName(username+usernameSN)!=null){
            usernameSN++;
        }
        return username + usernameSN;
    }

    public boolean delete(Integer id) throws SQLException {
        User user = this.find(id);
        return this.delete(user);
    }

    public boolean delete(User user) throws SQLException {
        return users.remove(user);
    }

    public Actor login(Connection connection, User user)
            throws SQLException {
        //创建Teacher类型的引用，暂不创建对象
        Actor currentActor = null;
        String sql_login = "SELECT * FROM user WHERE username =? and password=?";
        PreparedStatement pstmt_login =
                connection.prepareStatement(sql_login);
        pstmt_login.setString(1, user.getUsername());
        pstmt_login.setString(2, user.getPassword());
        ResultSet resultSet_login = pstmt_login.executeQuery();
        //如果表中存在id对应的记录，则获得表中的actor_id，并获得对应的Actor对象
        if (resultSet_login.next()) {
            int actor_id = resultSet_login.getInt("actor_id");
            currentActor = ActorService.getInstance().find(actor_id);
        }

        return currentActor;
    }
}
